import { defaultOptions, renderAsync } from 'docx-preview'
import * as PDFJS from 'pdfjs-dist/legacy/build/pdf'
import entry from 'pdfjs-dist/build/pdf.worker.entry'

PDFJS.GlobalWorkerOptions.workerSrc = entry
export default class FileView {
  private pdfInitData = {
    data: null, // PDF base64编码
    cMapPacked: true,
    pdfScale: 1.0,
    pdfPages: [], // 页数
    pdfWidth: '', // 宽度
    pdfSrc: '', // 地址
    pdfDoc: '', // 文档内容
    currentPage: 1
  }
  async renderWord(file, target, options?) {
    await renderAsync(
      file,
      target,
      undefined,
      Object.assign(defaultOptions, {
        debug: true,
        experimental: true,
        ...options
      })
    )
  }
  async renderPdf(parentEl: HTMLElement, file: File, options?) {
    const pdfData = {
      ...this.pdfInitData,
      ...options
    }
    const pdfDoc = await PDFJS.getDocument({
      ...pdfData,
      data: await dataURL(file)
    }).promise
    const pdfPages = pdfDoc.numPages
    const canvasBox = document.createElement('div')
    const canvasScrollBox = document.createElement('div')
    const data = { ...pdfData, parentEl, canvasBox, pdfPages, pdfDoc, num: 1 }
    this.elStyle(canvasBox, {
      margin: '0 auto',
      height: '100%'
    })
    this.elStyle(canvasScrollBox, {
      background: '#f2f2f2',
      overflow: 'auto',
      height: '100%'
    })
    parentEl.innerHTML = ''
    parentEl.appendChild(canvasScrollBox)
    canvasScrollBox.appendChild(canvasBox)
    await this.renderPage(data)
    this.createBtn(parentEl, data)
  }
  async renderPage(pdfData) {
    const canvas = document.createElement('canvas')
    const { canvasBox, pdfDoc, pdfPages, num } = pdfData
    const page = await pdfDoc.getPage(num)
    const ctx = canvas.getContext('2d')
    const dpr = window.devicePixelRatio || 1
    const bsr = 1
    const ratio = dpr / bsr
    const viewport = page.getViewport({ scale: pdfData.pdfScale })
    canvas.width = viewport.width * ratio
    canvas.height = viewport.height * ratio
    canvas.style.width = viewport.width + 'px'
    canvas.style.height = viewport.height + 'px'
    canvasBox.style.width = viewport.width + 'px'
    pdfData.pdfWidth = viewport.width + 'px'
    ctx && ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport
    }
    page.render(renderContext)
    if (pdfPages > num) {
      canvasBox.appendChild(canvas)
      pdfData.num += 1
      await this.renderPage(pdfData)
    }
  }
  createBtn(parentEl: HTMLElement, pdfData) {
    parentEl.style.position = 'relative'
    const box = document.createElement('div')
    const btn1 = document.createElement('span')
    const btn2 = document.createElement('span')
    const btnList = [btn1, btn2]
    this.elStyle(box, {
      display: 'flex',
      width: '60px',
      alignItems: 'center',
      justifyContent: 'space-between',
      fontSize: '20px',
      top: '10px',
      right: '20px',
      position: 'absolute',
      color: '#333'
    })
    btnList.forEach((item, index) => {
      this.elStyle(item, {
        border: '2px solid #333',
        borderRadius: '50%',
        width: '20px',
        height: '20px',
        lineHeight: '16px',
        textAlign: 'center',
        cursor: 'pointer'
      })
      box.appendChild(item)
      item.innerHTML = index === 0 ? '-' : '+'
      item.addEventListener('click', async () => {
        if (index === 0) {
          await this.scaleX(pdfData)
        } else await this.scaleD(pdfData)
      })
    })
    parentEl.appendChild(box)
  }
  elStyle(el: HTMLElement, styles: { [key: string]: string }) {
    for (const key in styles) {
      el.style[key] = styles[key]
    }
  }
  async scaleD(pdfData) {
    //放大
    let max = 0
    if (window.screen.width > 1440) {
      max = 2
    } else {
      max = 1.2
    }
    if (pdfData.pdfScale >= max) {
      return
    }
    pdfData.pdfScale = pdfData.pdfScale + 0.1
    pdfData.num = 1
    pdfData.canvasBox.innerHTML = ''
    await this.renderPage(pdfData)
  }
  async scaleX(pdfData) {
    //缩小
    const min = 1.0
    if (pdfData.pdfScale <= min) {
      return
    }
    pdfData.pdfScale = pdfData.pdfScale - 0.1
    pdfData.num = 1
    pdfData.canvasBox.innerHTML = ''
    await this.renderPage(pdfData)
  }
}

export async function readBuffer(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => {
      resolve(reader.result)
    }
    reader.onerror = reject
    reader.readAsArrayBuffer(file)
  })
}
export async function dataURL(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => {
      const data = atob(
        reader?.result?.substring(reader.result.indexOf(',') + 1)
      )
      resolve(data)
    }
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

export async function pdfToImg(file: File) {
  const loadingTask = PDFJS.getDocument({ data: await dataURL(file) }).promise
  const canvasArr: HTMLCanvasElement[] = []
  const promiseList: Promise[] = []
  return new Promise((resolve) => {
    loadingTask.then(async (pdf) => {
      // pdf 总页数
      const pages = pdf.numPages //声明一个pages变量等于当前pdf文件的页数

      for (let i = 1; i <= pages; i++) {
        //循环页数
        promiseList.push(renderCanvas(i))
      }
      for (const render of promiseList) {
        canvasArr.push(await render(pdf))
      }
      resolve(await exportImg(canvasArr))
    })
  })
}

function renderCanvas(i) {
  return async (pdf) => {
    const canvas = document.createElement('canvas')
    const page = await pdf.getPage(i) //调用getPage方法传入当前循环的页数,返回一个page对象
    const scale = 1 //缩放倍数，1表示原始大小
    const viewport = page.getViewport({ scale })
    const canvasContext = canvas.getContext('2d', 1) //创建绘制canvas的对象
    canvas.height = viewport.height //定义canvas高和宽
    canvas.width = viewport.width
    await page.render({
      canvasContext,
      viewport
    })
    return canvas
  }
}

async function exportImg(canvasArr) {
  return new Promise((resolve) => {
    setTimeout(() => {
      const imgList: HTMLImageElement[] = []
      for (let i = 0; i < canvasArr.length; i++) {
        const base64 = canvasArr[i].toDataURL('image/jpeg')
        imgList.push(base64)
      }
      resolve(imgList)
    }, 0)
  })
}
